function logProperty(target: any, key: string) {

  // 删除了原来的属性，用新的属性来对这个属性的 get 和 set 进行代理
  delete target[key];

  const backingField = "_" + key;

  // 代理方案是 defineProperty
  // 先初始化 代理方案
  Object.defineProperty(target, backingField, {
    writable: true,
    enumerable: true,
    configurable: true
  });

  // property getter
  const getter = function (this: any) {
    const currVal = this[backingField];
    console.log(`Get: ${key} => ${currVal}`);
    return currVal;
  };

  // property setter
  const setter = function (this: any, newVal: any) {
    console.log(`Set: ${key} => ${newVal}`);
    this[backingField] = newVal;
  };

  // Create new property with getter and setter
  // 再处理被代理方案
  Object.defineProperty(target, key, {
    get: getter,
    set: setter,
    enumerable: true,
    configurable: true
  });
}

class Person { 
  @logProperty
  public name: string;

  constructor(name : string) { 
    this.name = name;
  }
}

const p1 = new Person("semlinker");
p1.name = "kakuqo";
console.log(p1.name);
// 下面这段代码是可以运行的。
// console.log("p1._name", p1._name);
